package com.example.config.security.authority;
import com.example.util.SystemRole;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;
import java.util.Collection;

/**
 * 自定义访问决策类 3
 * @author wsl
 */
@Service("accessDecisionManager")
public class AccessDecisionManagerImpl implements AccessDecisionManager {

    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
        for (ConfigAttribute configAttribute : collection) {
            String needRole = configAttribute.getAttribute();//当前url所需角色
            //未受限资源直接放行（未登录也可访问的）
            if("NONE_LIMITATION".equals(needRole)){
                return;
            }
            //用户认证未通过
            if(authentication instanceof AnonymousAuthenticationToken) {
                throw new AccessDeniedException("尚未登录，请登录！");
            }
            //用户认证通过可访问
            if(SystemRole.ROLE_LOGIN.equalsIgnoreCase(needRole)){
                return;
            }
            //判断用户角色是否为url所需角色
            Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
            for (GrantedAuthority authority : authorities) {
                if(authority.getAuthority().equals(needRole)){
                    return;
                }
            }
        }
        throw new AccessDeniedException("没有访问权限");
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return false;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return false;
    }
}
